home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Design
/
WB Collection.iso
/
datatypes
/
debox_dt
/
source
/
dispatch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-07
|
11KB
|
462 lines
/******************************************************************************
*
* Flowerpower's DeBox Datatype
*
* Written by Christian Buchner and David N. Junod
*
******************************************************************************
* dispatch.c
*
* Sorry for Spaghetti code ;-)
*/
#include "classbase.h"
/*****************************************************************************/
#include <stdarg.h>
/* Message request routine */
void __stdargs Message(struct ClassBase *cb, UBYTE *Msg,...)
{
va_list Arg;
struct EasyStruct Req={sizeof(struct EasyStruct),0,"DeBox Request",0,"Okay"};
va_start(Arg,Msg);
Req.es_TextFormat=Msg;
EasyRequestArgs(NULL,&Req,0,Arg);
va_end(Arg);
}
/*****************************************************************************/
ULONG setdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
{
return (SetDTAttrsA (o, NULL, NULL, (struct TagItem *) & data));
}
/*****************************************************************************/
ULONG getdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
{
return (GetDTAttrsA (o, (struct TagItem *) & data));
}
/*****************************************************************************/
Class *initClass (struct ClassBase * cb)
{
Class *cl;
/* Create our class. Note that this particular class doesn't have any instance data */
if (cl = MakeClass (LibName, PICTUREDTCLASS, NULL, NULL, 0L))
{
cl->cl_Dispatcher.h_Entry = (ULONG (*)())Dispatch;
cl->cl_UserData = (ULONG) cb;
AddClass (cl);
}
return (cl);
}
/*****************************************************************************/
ULONG __asm Dispatch (register __a0 Class * cl, register __a2 Object * o, register __a1 Msg msg)
{
struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
ULONG retval;
switch (msg->MethodID)
{
case OM_NEW:
if (retval = DoSuperMethodA (cl, o, msg))
{
if (!GetPicture (cb, cl, (Object *) retval, ((struct opSet *) msg)->ops_AttrList))
{
CoerceMethod (cl, (Object *) retval, OM_DISPOSE);
return NULL;
}
}
break;
/* Let the superclass handle everything else */
default:
retval = (ULONG) DoSuperMethodA (cl, o, msg);
break;
}
return (retval);
}
/*****************************************************************************/
BOOL __asm GetPicture (register __a6 struct ClassBase * cb, register __a0 Class * cl, register __a2 Object * o, register __a1 struct TagItem * attrs)
{
BOOL Success = TRUE;
STRPTR title;
BPTR fh;
struct BitMapHeader *bmhd;
struct DeBoxChunk chunk;
UBYTE *image;
ULONG imagesize;
struct BitMap *bm=NULL;
ULONG modeid;
/* Get the default title */
title = (STRPTR) GetTagData (DTA_Name, NULL, attrs);
/* Get the file handle to read from and the BitMapHeader to write to */
if (!((getdtattrs (cb, o, DTA_Handle, &fh, PDTA_BitMapHeader, &bmhd, TAG_DONE) == 2) && fh))
{
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
Success=FALSE;
}
else
{
/* Seek to the beginning of the file */
Seek (fh, 0, OFFSET_BEGINNING);
/* Read in the first chunk header (similar to FORM header) */
if (Read(fh, &chunk, sizeof(chunk))!=sizeof(chunk))
{
SetIoErr(ERROR_BAD_HUNK);
Success=FALSE;
}
else
{
/* Check header CRC */
if (!DeBoxCRC(&chunk))
{
SetIoErr(ERROR_BAD_HUNK);
Success=FALSE;
}
else
{
/* Read out the image size (=chunk size) */
imagesize=chunk.chunk_len;
/* Allocate space for compressed image data */
if (!(image=AllocVec(imagesize,MEMF_PUBLIC)))
{
SetIoErr(ERROR_NO_FREE_STORE);
Success=FALSE;
}
else
{
/* Read compressed image data */
if (Read(fh, image, imagesize)!=imagesize)
{
SetIoErr(ERROR_BAD_HUNK);
Success=FALSE;
}
else
{
/* Decompress image data, create a Bitmap */
Success=DecrunchBitmap(cb,o,image,imagesize,&bm,bmhd,&modeid);
}
/* Compressed data is no longer needed */
FreeVec(image);
}
}
}
}
if (Success)
{
if (bm)
{
/* Set the attributes */
setdtattrs (cb, o,
DTA_ObjName, title,
DTA_NominalHoriz, bmhd->bmh_Width,
DTA_NominalVert, bmhd->bmh_Height,
PDTA_BitMap, bm,
PDTA_ModeID, modeid,
TAG_DONE);
}
}
else
{
/* On failure, just free the BitMap */
if (bm) FreeBitMap(bm);
}
return(Success);
}
BOOL DecrunchBitmap(struct ClassBase *cb, Object *o, UBYTE *buffer, ULONG size, struct BitMap **bm, struct BitMapHeader *bmhd, ULONG *modeid)
{
BOOL Success=TRUE;
struct DeBoxChunk *chunk;
UBYTE *data;
UWORD n;
UWORD *colors;
struct ColorRegister *cmap;
LONG *cregs;
UBYTE *sourcedata;
ULONG sourcesize;
UBYTE *destindata;
ULONG destinsize;
UBYTE *referencedata;
BOOL Extra=FALSE;
/* loop through chunks */
for ( chunk=(struct DeBoxChunk*)buffer ;
Success && ((UBYTE*)(chunk)<(buffer+size)) ;
chunk=(struct DeBoxChunk*)((UBYTE*)(chunk+1)+chunk->chunk_len) )
{
/* Check header CRC */
if (!DeBoxCRC(chunk))
{
SetIoErr(ERROR_BAD_HUNK);
Success=FALSE;
break;
}
else
{
/* set data start address */
data=(UBYTE*)(chunk+1);
// Message(cb, "Read chunk: %ld (%ld)\n"
// "Checksum: $%02lx\n"
// "HeaderMark: $%02lx\n"
// "DontKnow_02: $%04lx\n"
// "Flags: $%02lx\n"
// "CrunchMethod: $%02lx\n"
// "Destination Plane: $%02lx\n"
// "Reference Plane: $%02lx",
//
// chunk->chunk_len,
// chunk->decrunched_len,
// (ULONG)chunk->checksum,
// (ULONG)chunk->headermark,
// (ULONG)chunk->dontknow02,
// (ULONG)chunk->flags,
// (ULONG)chunk->crunchmethod,
// (ULONG)chunk->destinplane,
// (ULONG)chunk->referenceplane);
/* Init pointers */
sourcedata=data;
/* Get (corrected) size of chunk */
sourcesize=chunk->chunk_len;
if (chunk->flags&FLGF_SUBTRACT_ONE_BYTE) sourcesize--;
/* Get size of destination buffer */
destinsize=chunk->decrunched_len;
if (chunk->flags&FLGF_USE_EXTRA_BUFFER)
{
/* Allocate an extra buffer */
destinsize=*((ULONG*)sourcedata);
sourcesize-=sizeof(ULONG);
sourcedata+=sizeof(ULONG);
if (!(destindata=AllocVec(destinsize,MEMF_CLEAR)))
{
Message(cb,"No memory for extra buffer!");
SetIoErr(ERROR_NO_FREE_STORE);
Success=FALSE;
break;
}
Extra=TRUE;
}
else
{
/* See if we already have a bitmap */
if (*bm==NULL)
{
/* No: Allocate storage for DeBoxInfo structure */
/* (this structure may be crunched) */
if (!(destindata=AllocVec(destinsize,MEMF_PUBLIC)))
{
SetIoErr(ERROR_NO_FREE_STORE);
Success=FALSE;
break;
}
Extra=TRUE;
}
else
{
/* No extra buffer, bitmap exists */
/* so check and get destination plane */
if (chunk->destinplane>=bmhd->bmh_Depth)
{
SetIoErr(ERROR_BAD_HUNK);
Success=FALSE;
break;
}
destindata=(*bm)->Planes[chunk->destinplane];
}
}
/* Check and get reference plane */
if (*bm)
{
if (chunk->referenceplane>=bmhd->bmh_Depth)
{
SetIoErr(ERROR_BAD_HUNK);
Success=FALSE;
break;
}
referencedata=(*bm)->Planes[chunk->referenceplane];
}
else
{
referencedata=NULL;
}
/* Handle the different crunch methods */
switch(chunk->crunchmethod)
{
case CRUNCHMETHOD_PLAIN:
{
CopyMem(sourcedata,destindata,destinsize);
break;
}
case CRUNCHMETHOD_1:
{
Method_1(sourcedata,sourcesize,referencedata,destindata,destinsize);
break;
}
case CRUNCHMETHOD_2:
{
Method_2(sourcedata,sourcesize,referencedata,destindata,destinsize);
break;
}
case CRUNCHMETHOD_FILL:
{
if (sourcesize!=1)
{
SetIoErr(ERROR_BAD_HUNK);
Success=FALSE;
break;
}
else
{
memset(destindata,destinsize,*sourcedata);
}
break;
}
case CRUNCHMETHOD_4:
{
Method_4(sourcedata,sourcesize,referencedata,destindata,destinsize);
break;
}
case CRUNCHMETHOD_5:
{
Method_5(sourcedata,sourcesize,referencedata,destindata,destinsize);
break;
}
default:
{
SetIoErr(ERROR_BAD_HUNK);
Success=FALSE;
break;
}
}
if (Success)
{
/* XOR Delta decrunching */
if (chunk->flags&FLGF_XOR_REFERENCE_INTO_DEST)
{
XOR_Memory(referencedata,destindata,destinsize);
}
/* Now finally implemented: recursive decrunching */
if (chunk->flags&FLGF_USE_EXTRA_BUFFER)
{
Success=DecrunchBitmap(cb,o,destindata,destinsize,bm,bmhd,modeid);
}
/* Here we examine the DeBoxInfo structure and create a Bitmap */
if (*bm==NULL && Extra)
{
struct DeBoxInfo *info=(struct DeBoxInfo*)destindata;
/* Fill in the size information */
bmhd->bmh_Width = bmhd->bmh_PageWidth = info->width;
bmhd->bmh_Height = bmhd->bmh_PageHeight = info->height;
bmhd->bmh_Depth = info->depth;
/* Compute the mode ID */
*modeid = info->modeid & (HIRES|HAM|EXTRA_HALFBRITE|SUPERHIRES|DOUBLESCAN|LACE);
// Message(cb, "Width: %ld\n"
// "Height: %ld\n"
// "Depth: %ld\n"
// "Colors: %ld\n"
// "ModeID: %04lx",
// (ULONG)bmhd->bmh_Width,
// (ULONG)bmhd->bmh_Height,
// (ULONG)bmhd->bmh_Depth,
// (ULONG)info->numcolors,
// (ULONG)*modeid);
/* Set the number of colors */
setdtattrs (cb, o, PDTA_NumColors, info->numcolors, TAG_DONE);
/* Get the destination for the color information */
getdtattrs (cb, o,
PDTA_ColorRegisters, (ULONG)&cmap,
PDTA_CRegs, &cregs,
TAG_DONE);
/* Get pointer to palette array */
colors=(UWORD*)((UBYTE*)(info)+info->palette_offset);
/* Set the color information */
for (n=0; n < info->numcolors; n++)
{
/* Set the master color table */
cmap->red = ((*colors&0xF00)>>4)|((*colors&0xF00)>>8);
cmap->green=((*colors&0x0F0) )|((*colors&0x0F0)>>4);
cmap->blue =((*colors&0x00F)<<4)|((*colors&0x00F) );
/* Set the color table used for remapping */
cregs[n * 3 + 0] = cmap->red << 24;
cregs[n * 3 + 1] = cmap->green << 24;
cregs[n * 3 + 2] = cmap->blue << 24;
colors++;
cmap++;
}
/* Allocate the bitmap */
if (!(*bm = AllocBitMap (bmhd->bmh_Width, bmhd->bmh_Height, bmhd->bmh_Depth, BMF_CLEAR, NULL)))
{
SetIoErr(ERROR_NO_FREE_STORE);
Success=FALSE;
break;
}
/* Allow further chunk processing */
chunk->flags|=FLGF_ANOTHER_CHUNK_FOLLOWS;
}
/* Free any existing extra buffers */
if (Extra)
{
FreeVec(destindata);
Extra=FALSE;
}
}
/* See if some more chunks will follow */
if (!(chunk->flags&FLGF_ANOTHER_CHUNK_FOLLOWS))
{
break;
}
}
}
/* Just in case we broke out of the loop */
/* Free any existing extra buffers */
if (Extra)
{
FreeVec(destindata);
Extra=FALSE;
}
return(Success);
}